package com.lanchetech.admin.service.impl;


import com.google.code.kaptcha.impl.DefaultKaptcha;
import com.lanchetech.admin.config.JwtAuthenticationRequest;
import com.lanchetech.admin.config.JwtTokenUtil;
import com.lanchetech.admin.service.AdminAuthService;
import com.lanchetech.bean.response.ResultData;
import com.lanchetech.common.enums.ResultCode;
import com.lanchetech.dao.AdminMapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;

import javax.imageio.ImageIO;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.awt.image.BufferedImage;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.util.Base64;

@Service
public class AdminAuthServiceImpl implements AdminAuthService {

    private AuthenticationManager authenticationManager;
    private UserDetailsService userDetailsService;
    private JwtTokenUtil jwtTokenUtil;
    private AdminMapper adminDAO;

    @Autowired
    DefaultKaptcha defaultKaptcha;

    @Value("${jwt.tokenHead}")
    private String tokenHead;

    @Autowired
    public AdminAuthServiceImpl(
            AuthenticationManager authenticationManager,
            @Qualifier("customUserService") UserDetailsService userDetailsService,
            JwtTokenUtil jwtTokenUtil,
            AdminMapper adminDAO) {
        this.authenticationManager = authenticationManager;
        this.userDetailsService = userDetailsService;
        this.jwtTokenUtil = jwtTokenUtil;
        this.adminDAO = adminDAO;
    }

    @Override
    public ResultData<String> login(JwtAuthenticationRequest req, HttpSession session) {
        ResultData<String> resultData = new ResultData<>();

        Boolean isValidateCaptcha = validateCaptcha(session.getAttribute("captchaKey"), req.getCode());

        if (!isValidateCaptcha) {
            resultData.setResultCode(ResultCode.CAPTCHA_WRONG);
            session.removeAttribute("captchaKey");
            return resultData;
        }

        try {
            UsernamePasswordAuthenticationToken upToken = new UsernamePasswordAuthenticationToken(req.getUsername(), req.getPassword());
            final Authentication authentication = authenticationManager.authenticate(upToken);
            SecurityContextHolder.getContext().setAuthentication(authentication);
            final UserDetails userDetails = userDetailsService.loadUserByUsername(req.getUsername());
            final String token = jwtTokenUtil.generateToken(userDetails);
            resultData.setValue(token);
            session.removeAttribute("captchaKey");
        } catch (Exception e) {
            resultData.setResultCode(ResultCode.USERNAME_OR_PASSWORD_ERROR);
            session.removeAttribute("captchaKey");
        }

        return resultData;
    }

    private Boolean validateCaptcha(Object captcha, String code) {
        Long towMinutesTime = 120000L;
        Integer codeLength = 4;

        if (captcha == null || code == null || code.length() != codeLength) {
            return false;
        }

        Long time = System.currentTimeMillis();
        String[] captchaArray = captcha.toString().split(",");
        Long captchaTime = new Long(captchaArray[0]);
        if (time > captchaTime + towMinutesTime) {
            return false;
        }

        return code.equals(captchaArray[1]);
    }

    @Override
    public ResultData<String> getKaptchaImageBase64(HttpServletResponse response, HttpSession session) {
        response.setDateHeader("Expires", 0);
        response.setHeader("Cache-Control", "no-store, no-cache, must-revalidate");
        response.addHeader("Cache-Control", "post-check=0, pre-check=0");
        response.setHeader("Pragma", "no-cache");
        response.setContentType("image/jpeg");

        String capText = defaultKaptcha.createText();
        //capText是由图形验证码随机生成的4个字符
        System.out.println("capText: " + capText);

        Long time = System.currentTimeMillis();
        try {
            session.setAttribute("captchaKey", time.toString() + "," + capText);
        } catch (Exception e) {
            e.printStackTrace();
        }

        BufferedImage bi = defaultKaptcha.createImage(capText);
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        try {
            ImageIO.write(bi, "jpg", out);
        } catch (IOException e) {
            e.printStackTrace();
        }
        byte[] bytes = out.toByteArray();
        Base64.Encoder base64Encoder = Base64.getEncoder();
        return new ResultData<>(base64Encoder.encodeToString(bytes));
    }
}